"""
Case Type   : reindex
Case Name   : 20个会话同时对一个表反复reindex,观察是否成功重建
Create At   : 2022/03/07
Owner       : liu-tong-8848
Description :
    1.建表1
    2.向表1中插入数据
    3.创建索引
    4.循环生成20个线程,同时对表进行在线reindex
    5.查询表结构是否损坏
    6.清理环境
Expect      :
    1.建表1成功
    2.向表1中插入数据成功
    3.创建索引成功
    4.反复对表reindex成功
    5.返回查询的数据,表结构未被损坏
    6.清理环境成功
History     :
"""

import os
import time
import unittest
from yat.test import Node
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.ComThread import ComThread
from testcase.utils.Logger import Logger


class SQL(unittest.TestCase):
    def setUp(self):
        self.logger = Logger()
        self.logger.info(f'-----{os.path.basename(__file__)} start-----')
        self.dbuserNode = Node('PrimaryDbUser')
        self.primary_sh = CommonSH('PrimaryDbUser')
        self.table = 't_reindex_concurrently_0067'
        self.index = 'i_reindex_concurrently_0067'
        self.Constant = Constant()

    def test_reindex(self):
        self.logger.info(f'-----{os.path.basename(__file__)} start-----')
        step1 = 'step1:建表1 expect:建表1成功'
        self.logger.info(step1)
        create_table = self.primary_sh.execut_db_sql(f'''
            drop table if exists {self.table};
            create table {self.table}(name varchar(10),stu_id varchar(5) not 
            null,score int,num int );;''')
        self.logger.info(create_table)
        self.assertIn(self.Constant.TABLE_DROP_SUCCESS, create_table,
                      "执行失败" + step1)
        self.assertIn(self.Constant.CREATE_TABLE_SUCCESS, create_table,
                      "建表1失败" + step1)

        step2 = 'step2:向表1中插入数据 expect:向表1中插入数据成功'
        self.logger.info(step2)
        insert_data = self.primary_sh.execut_db_sql(
            f'''insert into {self.table} values('数学','01', 90,
            generate_series(1,500));''')
        self.logger.info(insert_data)
        self.assertIn(self.Constant.INSERT_SUCCESS_MSG, insert_data,
                      "向表1中插入数据失败" + step2)

        step3 = 'step3:创建索引 expect:创建索引成功'
        self.logger.info(step3)
        create_index = self.primary_sh.execut_db_sql(
            f'''drop index if exists {self.index};
            create index {self.index} on {self.table} using btree(num);''')
        self.logger.info(create_index)
        self.assertIn(self.Constant.DROP_INDEX_SUCCESS_MSG, create_index,
                      "执行失败" + step3)
        self.assertIn(self.Constant.CREATE_INDEX_SUCCESS_MSG, create_index,
                      "执行失败" + step3)

        step4 = 'step4:循环生成20个线程,同时对表进行在线reindex' \
                ' expect:反复对表reindex成功'
        self.logger.info(step4)
        reindex = f'''reindex table concurrently {self.table};
            select pg_sleep(20);'''
        threads = []
        for i in range(0, 19):
            session1 = ComThread(self.primary_sh.execut_db_sql,
                                 args=(reindex,))
            threads.append(session1)
        thread_results = []
        self.logger.info("生成线程，这里之后报错的话，可以尝试调整sshd_config的MaxSessions超过20")
        for t in threads:
            t.setDaemon(True)
            t.start()
        for t in threads:
            t.join(30)
            thread_results.append(t.get_result())
        self.logger.info(thread_results)
        thread_results1 = str(thread_results)
        self.assertIn(self.Constant.REINDEX_SUCCESS_MSG, thread_results1, '执行失败' +
                         step4)

        step5 = 'step5:查询表数据,分析表结构是否损坏 ' \
                'expect:返回查询的数据,表结构未被损坏'
        self.logger.info(step5)
        select_index = self.primary_sh.execut_db_sql(
            f'''select * from {self.table} where num <= 100;''')
        self.logger.info(select_index)
        self.assertIn('100 rows', select_index, '执行失败' + step5)

    def tearDown(self):
        step6 = 'step6:清理环境 expect:清理环境成功'
        self.logger.info(step6)
        clean_environment = self.primary_sh.execut_db_sql(
            f'''drop table {self.table} cascade;''')
        self.logger.info(clean_environment)
        self.assertIn(self.Constant.TABLE_DROP_SUCCESS, clean_environment,
                      '执行失败' + step6)
        self.logger.info(f'-----{os.path.basename(__file__)} end-----')
